<!--
 * Copyright ©
 * #  
 * @author: zw
 * @date: 2022-04-06 
 -->


<template>
  <el-row class="w-full h-full bg-yellow-100">
    <el-col class="panel" :span="8">
      <el-col class="item" @click.native="marking(1)">绘点</el-col>
      <el-col class="item" @click.native="marking(2)">绘线</el-col>
      <el-col class="item" @click.native="marking(3)">绘多边形</el-col>
      <el-col class="item" @click.native="marking(4)">绘正方形</el-col>
      <el-col class="item" @click.native="marking(5)">绘矩形</el-col>
      <el-col class="item" @click.native="marking(6)">绘圆</el-col>
      <el-col class="item" @click.native="marking(7)">编辑</el-col>
    </el-col>

    <el-drawer v-drag:classList="{head: 'el-drawer__header', wrap: 'el-drawer__container'}" :visible.sync="visible" direction="ltr" :withHeader="true" size="100%" :modal-append-to-body="false" :show-close="false" :close-on-press-escape="false" :modal="false" :wrapperClosable="false" @close="close">
      <template #title>
        <el-alert v-if="visible" class="select-none" show-icon type="info" :closable="true" effect="dark" :title="panelHeadTitle" :description="panelTip" @close="visible = !visible" />
      </template>
      <el-card v-if="formVisible" class="h-full" :body-style="{height: '100%', paddingLeft: 0}">
        <el-form ref="form" :model="form" label-width="80px" size="mini">
          <el-form-item>
            <el-tag class="block" v-if="subTip" type="success" effect="dark">{{subTip}}</el-tag>
          </el-form-item>

          <el-form-item label="操作">
            <el-button type="primary" icon="el-icon-position" @click="addSelectInteraction">选择</el-button>
            <el-button type="warning" icon="el-icon-rank" @click="addTranslateInteraction">平移</el-button>
            <el-button type="success" icon="el-icon-share" @click="addModifyInteraction">节点操作</el-button>
            <el-button type="danger" icon="el-icon-delete" @click="addDeleteInteraction">删除</el-button>
          </el-form-item>

          <el-form-item label="名称">
            <el-input v-model="form.name" placeholder="请输入标注名称" />
          </el-form-item>
          <el-form-item label="备注">
            <el-input v-model="form.label" placeholder="请输入标注备注" />
          </el-form-item>
          <el-form-item label="面样式">
            <el-color-picker v-model="form.colorSide" show-alpha :predefine="form.predefineColors" />
          </el-form-item>
          <el-form-item label="线样式">
            <el-color-picker v-model="form.colorLine" show-alpha :predefine="form.predefineColors" />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="infoSave">保存</el-button>
          </el-form-item>
        </el-form>
      </el-card>
    </el-drawer>

  </el-row>
</template>

<script>
import { fromLonLat } from "./transform";
import { __checkLayerVector, __findLayer, __checkInteractDraw } from ".";
import { markLayerStyle, drawStyleFunc, markStyle, style_modify, style_selected_modify, style_selected } from "./style";
import { newId, addFeatureToLocalstorage, localstorageGet, localstorageSet } from "./tools";
let map, style;
var lastDrawFeature;
export default {
  name: 'Layer',
  data() {
    return {
      map: null,
      drawType: null,
      panelHeadTitle: "",
      panelTip: "",
      subTip: "",
      visible: false,
      drawInteracLayer: null, // 绘制layer
      drawInteracSource: null, // 绘制layer
      drawInteraction: null, // drawInteraction
      selectInteraction: null,
      formVisible: false,
      form: {
        name: "",
        label: "",
        colorSide: "",
        colorLine: "",
        predefineColors: ['#ff4500', '#ff8c00', '#ffd700', '#90ee90', '#00ced1', '#1e90ff', '#c71585', 'rgba(255, 69, 0, 0.68)', 'rgb(255, 120, 0)', 'hsv(51, 100, 98)', 'hsva(120, 40, 94, 0.5)', 'hsl(181, 100%, 37%)', 'hsla(209, 100%, 56%, 0.73)', '#c7158577']
      }
    };
  },

  mounted() {
    this.initMap();
  },

  methods: {
    initMap() {
      const view = new ol.View({ center: fromLonLat([114, 30]), zoom: 13 });
      map = new ol.Map({ target: this.$el, view });
      this.map = map;
      this.readLocalFeature();
    },
    marking(type) {
      let drawType = null;
      this.clearAllMapInteraction();
      let panelHeadTitle, panelTip;
      switch (type) {
        case 1:
          drawType = 'Point';
          panelHeadTitle = "绘制点标注";
          panelTip = "地图上待标注位置鼠标左键点击地图添加一个点标注，可填写名称、备注、图标，点击保存生效！";
          break;
        case 2:
          drawType = "LineString";
          panelHeadTitle = "绘制线标注";
          panelTip = "地图上待标注位置鼠标左键依次点击地图绘制线，双击鼠标左键结束绘制，可填写名称、备注、线样式，点击保存生效！";
          break;
        case 3:
          drawType = "Polygon";
          panelHeadTitle = "绘制多边形标注";
          panelTip = "地图上待标注位置鼠标左键依次点击地图绘制面，双击鼠标左键结束绘制，可填写名称、备注、面样式，点击保存生效！";
          break;
        case 4:
          drawType = "Circle";
          panelHeadTitle = "绘制矩形标注";
          panelTip = "地图上鼠标左键依次点击矩形中心点和右下角完成绘制，双击鼠标左键结束绘制，可填写名称、备注、面样式，点击保存生效！";
          break;
        case 5:
          drawType = 'Circle';
          panelHeadTitle = "绘制长方形标注";
          panelTip = "地图上鼠标左键依次点击长方形左上角和右下角完成绘制，双击鼠标左键结束绘制，可填写名称、备注、面样式，点击保存生效！";
          break;
        case 6:
          drawType = "Circle";
          panelHeadTitle = "绘制圆形标注";
          panelTip = "地图上鼠标左键依次点击圆形中心点和圆上任意一点完成绘制，双击鼠标左键结束绘制，可填写名称、备注、圆样式，点击保存生效！";
          break;
        case 7:
          drawType = 'edit';
          panelHeadTitle = "标注编辑";
          panelTip = "选择需要编辑的标注进行编辑！";
          break
      }
      if (drawType != 'edit') {
        this.addDrawInteraction(drawType);
      } else {
        this.addSelectInteraction();
      }
      this.panelHeadTitle = panelHeadTitle;
      this.panelTip = panelTip;
      this.visible = true;
    },
    addDrawInteraction(type) {
      const layer = __findLayer(map, "name", "drawInteracLayer");
      layer.setStyle(markLayerStyle);
      const draw = __checkInteractDraw.call(this, map, "drawInteraction", "drawInteracSource", type, drawStyleFunc(type, markStyle));
      draw.on('drawstart', (e) => {
        Object.assign(this.$data.form, this.$options.data().form);
        this.formVisible = false;
      });
      draw.on('drawend', (e) => {
        lastDrawFeature = e.feature;
        lastDrawFeature.setId(newId());
        lastDrawFeature.set('style', JSON.stringify(markStyle));
        lastDrawFeature.set('name', "");
        lastDrawFeature.set('remark', '');
        addFeatureToLocalstorage(lastDrawFeature);
        this.formVisible = true;
      });
    },
    addSelectInteraction() {
      this.clearAllMapInteraction();
      const layer = __findLayer(map, "name", "drawInteracLayer");
      const source = layer.getSource();
      const selectInteraction = new ol.interaction.Select();
      map.addInteraction(selectInteraction);
      selectInteraction.on("select", e => {
        if (e.selected.length <= 0) return;
        this.formVisible = true;
        const feature = e.selected[0];
        lastDrawFeature = feature;
        this.form.name = feature.get('name');
        this.form.label = feature.get('remark');
        style = JSON.parse(feature.get('style'));
      });
      const snap = new ol.interaction.Snap({ pixelTolerance: 20, source });
      map.addInteraction(snap);
      this.subTip = "鼠标左键点击选择标注对象";
      this.selectInteraction = selectInteraction;
    },
    addTranslateInteraction() {
      const layer = __findLayer(map, "name", "drawInteracLayer");
      const source = layer.getSource();
      this.clearAllMapInteraction();
      var translate = new ol.interaction.Translate({ layers: [layer] });
      map.addInteraction(translate);
      translate.on('translateend', (e) => {
        for (var i = 0; i < e.features.getLength(); i++) {
          var feature = e.features.item(i);
          addFeatureToLocalstorage(feature);
        }
      });
      var snap = new ol.interaction.Snap({ pixelTolerance: 20, source });
      map.addInteraction(snap)
    },
    addModifyInteraction() {
      const layer = __findLayer(map, "name", "drawInteracLayer");
      const source = layer.getSource();
      this.clearAllMapInteraction();
      const selectInteraction = new ol.interaction.Select({ style: style_selected_modify });
      const modify = new ol.interaction.Modify({ style: style_modify, features: selectInteraction.getFeatures() });
      const snap = new ol.interaction.Snap({ pixelTolerance: 20, source });
      modify.on('modifyend', (e) => {
        for (var i = 0; i < e.features.getLength(); i++) {
          var feature = e.features.item(i);
          addFeatureToLocalstorage(feature)
        }
      });
      map.addInteraction(selectInteraction);
      map.addInteraction(modify);
      map.addInteraction(snap);
      this.subTip = "鼠标左键点击选择待编辑的标注对象，选中之后标注样式变红色；点标注可拖动，线和面标注可添加、删除、拖动节点";
      this.selectInteraction = selectInteraction;
    },
    addDeleteInteraction() {
      this.clearAllMapInteraction();
      const layer = __findLayer(map, "name", "drawInteracLayer");
      const selectInteraction = new ol.interaction.Select({ style: style_selected });
      const snap = new ol.interaction.Snap({ pixelTolerance: 20, source: layer.getSource() });
      selectInteraction.on('select', async (e) => {
        var features = e.selected;
        var num = features.length;
        if (num <= 0) return;
        const confirmResult = await this.$confirm("此操作将删除画面要素, 是否继续?", "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }).catch(err => err); // 确认 = confirm; 取消 = cancel
        if (confirmResult !== "confirm") return this.$message.info("取消操作！");
        for (var index = 0; index < num; index++) {
          var feature = features[0];
          layer.getSource().removeFeature(feature);
          this.deleteFeatureFromLocalstorage(feature);
        }
        selectInteraction.getFeatures().clear();
      });

      map.addInteraction(selectInteraction);
      map.addInteraction(snap);
      this.selectInteraction = selectInteraction;
      this.subTip = "鼠标左键点击待删除标注，弹出提示框选择“确定”删除标注";
    },
    deleteFeatureFromLocalstorage(feature) {
      var featureList = localstorageGet('featureList');
      if (!featureList) return;
      for (var index = 0; index < featureList.length; index++) {
        var element = featureList[index];
        if (element.id == feature.getId()) {
          featureList.splice(index, 1);
          localstorageSet('featureList', featureList);
          break
        }
      }
    },
    clearAllMapInteraction() {
      var interactions = map.getInteractions();
      var length = interactions.getLength();
      for (var i = 9; i < length; i++) {
        var interaction = interactions.item(9);
        if (interaction instanceof ol.interaction.Select) {
          interaction.getFeatures().clear()
        }
        map.removeInteraction(interaction)
      }
    },
    infoSave() {
      const { name, label, colorSide, colorLine } = this.form;
      style = JSON.parse(JSON.stringify(markStyle));
      style.polygon.fillColor = colorSide;
      style.polygon.borderColor = colorLine;
      lastDrawFeature.set('name', name);
      lastDrawFeature.set('remark', label);
      lastDrawFeature.set('style', JSON.stringify(style));
      addFeatureToLocalstorage(lastDrawFeature);
      if (this.selectInteraction) {
        this.selectInteraction.getFeatures().clear();
      }
    },
    readLocalFeature() {
      const featureListCache = localstorageGet('featureList');
      const { layer } = __checkLayerVector.call(this, map, "drawInteracLayer", "drawInteracSource");
      if (!featureListCache) return;
      for (var index = 0; index < featureListCache.length; index++) {
        var featureObj = featureListCache[index];
        var feature = new ol.Feature();
        switch (featureObj.type) {
          case "Point":
            feature.setGeometry(new ol.geom.Point(featureObj.coordinates[0]));
            break;
          case "LineString":
            feature.setGeometry(new ol.geom.LineString(featureObj.coordinates));
            break;
          case "Polygon":
            feature.setGeometry(new ol.geom.Polygon(featureObj.coordinates));
            break;
          case "Circle":
            feature.setGeometry(new ol.geom.Circle(featureObj.coordinates[0], featureObj.coordinates[1]));
            break
        }
        feature.setId(featureObj.id);
        feature.set('name', featureObj.name);
        feature.set('remark', featureObj.remark);
        feature.set('style', featureObj.style);
        layer.getSource().addFeature(feature)
      }
    },
    close() { },

  }
  //  End
}

</script>

<style lang='scss' scoped>
.panel {
  @apply absolute z-10 right-0 flex text-center items-center;
  .item {
    @apply py-1 rounded-lg hover:bg-gray-300 hover:text-blue-500 cursor-pointer select-none;
  }
}
.el-drawer__wrapper {
  user-select: none;
  pointer-events: none;
  /deep/ .el-drawer__container {
    pointer-events: auto;
    width: 30%;
    right: unset;
    bottom: unset;
    height: unset;
    .el-drawer {
      height: unset;
      bottom: unset;
      .el-drawer__header {
        margin-bottom: 16px;
      }
    }
  }
  /deep/ .el-alert__description {
    line-height: 25px;
    margin: 0;
  }
}
</style>
